#define _POSIX_C_SOURCE 200809L  // 为了使用 strdup

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "preprocess.h"
#include "grouping.h"

// 处理文件输入输出并进行分组分析
void process_and_group_logs(const char* input_filename, const char* output_filename) {
    printf("开始处理日志文件并分析分组: %s -> %s\n", input_filename, output_filename);
    
    // 初始化预处理模块
    if (!preprocess_init()) {
        fprintf(stderr, "预处理模块初始化失败\n");
        exit(EXIT_FAILURE);
    }
    
    // 初始化分组管理器
    GroupManager* gm = group_manager_init();
    if (!gm) {
        fprintf(stderr, "分组管理器初始化失败\n");
        preprocess_cleanup();
        exit(EXIT_FAILURE);
    }
    
    FILE* input_file = fopen(input_filename, "r");
    if (!input_file) {
        perror("无法打开输入文件");
        group_manager_free(gm);
        preprocess_cleanup();
        exit(EXIT_FAILURE);
    }
    
    FILE* output_file = fopen(output_filename, "w");
    if (!output_file) {
        perror("无法打开输出文件");
        fclose(input_file);
        group_manager_free(gm);
        preprocess_cleanup();
        exit(EXIT_FAILURE);
    }
    
    char line[4096];
    int line_count = 0;
    int processed_count = 0;
    clock_t start_time = clock();
    
    printf("正在处理日志文件并进行分组分析...\n");
    
    while (fgets(line, sizeof(line), input_file) != NULL) {
        line_count++;
        
        // 去除换行符
        size_t len = strlen(line);
        if (len > 0 && line[len-1] == '\n') {
            line[len-1] = '\0';
        }
        
        // 跳过空行
        if (strlen(line) == 0) {
            continue;
        }
        
        // 处理日志行
        printf("处理第 %d 行: %s\n", line_count, line);
        char* processed = preprocess_log(line);
        if (processed) {
            printf("预处理结果: %s\n", processed);
            
            // 分词处理
            char** tokens = NULL;
            uint32_t token_count = 0;
            tokens = tokenize_string(processed, &token_count);
            
            if (tokens && token_count > 0) {
                printf("分词结果 (%d 个词): ", token_count);
                for (int i = 0; i < token_count; i++) {
                    printf("%s ", tokens[i]);
                }
                printf("\n");
                
                // 分组处理 - 需要将 char** 转换为 const char**
                const char** const_tokens = (const char**)tokens;
                int group_id = group_manager_process(gm, const_tokens, token_count);
                printf("分组ID: %d\n", group_id);
                
                // 输出到文件：分组ID + 原始日志
                fprintf(output_file, "[Group %d] %s\n", group_id, line);
                
                // 释放分词内存
                free_tokens(tokens, token_count);
                
                processed_count++;
            } else {
                printf("分词失败\n");
                fprintf(output_file, "[Group -1] %s\n", line);
            }
            
            free(processed);
        } else {
            printf("预处理失败\n");
            fprintf(output_file, "[Group -1] %s\n", line);
        }
        
        printf("--------------------\n");
        
        // 只处理前几行用于调试
        if (line_count >= 2000) {
            printf("只处理前5行用于调试\n");
            break;
        }
    }
    
    clock_t end_time = clock();
    double elapsed_time = (double)(end_time - start_time) / CLOCKS_PER_SEC;
    
    printf("处理完成!\n");
    printf("统计信息:\n");
    printf("- 总行数: %d\n", line_count);
    printf("- 成功处理行数: %d\n", processed_count);
    printf("- 耗时: %.2f 秒\n", elapsed_time);
    if (elapsed_time > 0) {
        printf("- 平均速度: %.2f 行/秒\n", line_count / elapsed_time);
    }
    
    // 打印分组统计
    printf("\n分组统计结果:\n");
    group_manager_print_groups(gm);
    
    fclose(input_file);
    fclose(output_file);
    
    // 清理资源
    group_manager_free(gm);
    preprocess_cleanup();
}

int main(int argc, char* argv[]) {
    if (argc != 3) {
        printf("用法: %s 输入文件 输出文件\n", argv[0]);
        printf("示例: %s Linux_2k.log grouped_output.log\n", argv[0]);
        return EXIT_FAILURE;
    }
    
    process_and_group_logs(argv[1], argv[2]);
    
    return EXIT_SUCCESS;
}